//
// Created by YueChuan on 2023/4/25.
//
#include "socket.h"
#include "iomanager.h"
#include <string>
#include <netinet/tcp.h>
static yuechuan::Logger::ptr g_logger = YUECHUAN_LOG_ROOT();

void test_socket() {
    yuechuan::IPAddress::ptr address = yuechuan::Address::LookupAnyIPAddress("www.baidu.com");
    if (address) {
        YUECHUAN_LOG_INFO(g_logger) << "get address: " << address->toString();
    } else {
        YUECHUAN_LOG_ERROR(g_logger) << "get address error ";
        return;
    }
    yuechuan::Socket::ptr sock = yuechuan::Socket::CreateTCP(address);
    YUECHUAN_LOG_INFO(g_logger) << "sock = " << sock->getSock();
    address->setPort(80);
    YUECHUAN_LOG_INFO(g_logger) << "addr = " << address->toString();
    if (!sock->connect(address)) {
        YUECHUAN_LOG_ERROR(g_logger) << "connect " << address->toString() << " fail";
        YUECHUAN_LOG_ERROR(g_logger) << "errno = " << strerror(errno);
        return;
    } else {
        YUECHUAN_LOG_INFO(g_logger) << "connect " << address->toString() << "connected";
    }
    const char buff[] = "GET / HTTP/1.0\r\n\r\n";
    int rt = sock->send(buff, sizeof(buff));
    if (rt <= 0) {
        YUECHUAN_LOG_ERROR(g_logger) << "send fail rt =" << rt;
        return;
    }

    std::string buffs;
    buffs.resize(4096);
    rt = sock->recv(&buffs[0], buffs.size());

    if (rt <= 0) {
        YUECHUAN_LOG_ERROR(g_logger) << "recv fail rt = " << rt;
        return;
    }

    buffs.resize(rt);
    YUECHUAN_LOG_INFO(g_logger) << buffs;

}

void test2() {
    yuechuan::IPAddress::ptr addr = yuechuan::Address::LookupAnyIPAddress("www.baidu.com:80");
    if (addr) {
        YUECHUAN_LOG_INFO(g_logger) << "get address : " << addr->toString();
    } else {
        YUECHUAN_LOG_ERROR(g_logger) << "get address fail";
        return;
    }
    yuechuan::Socket::ptr sock = yuechuan::Socket::CreateTCP(addr);
    if (!sock->connect(addr)) {
        YUECHUAN_LOG_ERROR(g_logger) << "connect " << addr->toString() << " fail";
    } else {
        YUECHUAN_LOG_INFO(g_logger) << "connect " << addr->toString() << " connected";
    }
    uint64_t ts = yuechuan::GetCurrentTimeUS();
    for (size_t i = 0; i < 10000000000ul; ++i) {
        if (int err = sock->getError()) {
            YUECHUAN_LOG_INFO(g_logger) << "err = " << err << " errstr = " << strerror(err);
            break;
        }
        struct tcp_info tcp_info;
        if(!sock->getOption(IPPROTO_TCP, TCP_INFO, tcp_info)) {
            YUECHUAN_LOG_INFO(g_logger) << "err";
            break;
        }
        if(tcp_info.tcpi_state != TCP_ESTABLISHED) {
            YUECHUAN_LOG_INFO(g_logger)
                    << " state=" << (int)tcp_info.tcpi_state;
            break;
        }
        static int batch = 10000000;
        if (i && (i % batch) == 0) {
            uint64_t ts2 = yuechuan::GetCurrentTimeUS();
            YUECHUAN_LOG_INFO(g_logger) << "i = " << i << " used: " << ((ts2 - ts) * 1.0 / batch) << " us ";
            ts = ts2;
        }
    }

}

int main(int argc, char **argv) {
    yuechuan::IOManager iom;
//    iom.schedule(&test_socket);
    iom.schedule(&test2);
    return 0;
}
